from typing import Any, Optional
from datetime import datetime, timedelta, timezone

from services.wx_friends_service import set_friends_remark
from utils.minio_util import url_to_base64_async
# from utils.ollama import generate_description
from utils.sender_tools import SenderTools

import redis.asyncio as redis

from core.config import settings
from core.logger import log
from db.models.chat_message import ChatMessageModel,ContentType
from db.models.inc import SequenceCounter
from db.models.wx_friends import MessageParams
from services.redis_service import AsyncRedisService
from services.wx_user_service import get_wx_id_by_token_key
from utils.result import Result
from fastapi import Query, HTTPException


async def create_wx_messages(sender_id: str, receiver_id: str,type: str, content: Any,file_id: str = None,content_type: int=None):
    session_id = ChatMessageModel.generate_session_id(sender_id,receiver_id)
    seq_id = await SequenceCounter.get_next_sequence(session_id)
    new_msg = {
        # "msg_id": uuid.uuid4(),
        "seq_id": seq_id,
        "session_id": session_id,
        "sender_id": sender_id,
        "receiver_id": receiver_id,
        "content": content,
        "type":type,
        "gridfs_file_id":file_id,
        "content_type":content_type if content_type else 1,
    }

    try:
        msg_model = ChatMessageModel(**new_msg)
        await msg_model.insert()
    except Exception as e:
        # 根据实际日志系统记录异常信息
        log.info(f"Failed to insert message: {e}")
        # 可替换为 logging.error 等方式
        raise HTTPException(status_code=500, detail="插入消息失败")

async def delete_wx_message(sender: str,receiver: str):
    try:
        session_id = ChatMessageModel.generate_session_id(send_id=sender, receiver_id=receiver)
        await ChatMessageModel.find(ChatMessageModel.session_id == session_id).delete_many()
        return Result.success()
    except Exception as e:
        log.info(f"Failed to delete message: {e}")
        return Result.fail(msg="删除消息失败")
async def get_wx_messages():
    try:
        messages = await ChatMessageModel.find_all().to_list()
        messages = [msg.dict() for msg in messages]
        return messages
    except Exception as e:
        # 根据实际日志系统记录异常信息
        print(f"Failed to retrieve messages: {e}")
        # 可替换为 logging.error 等方式
        return  []

async def get_wx_messages_by_session_id(sender_id: str, receiver_id: str):
    """
    获取会话历史消息
    :param sender_id: 发送者id
    :param receiver_id: 接受者id
    :return:
    """
    try:
        session_id = ChatMessageModel.generate_session_id(send_id=sender_id, receiver_id=receiver_id)
        messages = await ChatMessageModel.find(ChatMessageModel.session_id==session_id).sort("seq_id").to_list()
        messages = [msg.dict() for msg in messages]
        return messages
    except Exception as e:
        # 根据实际日志系统记录异常信息
        print(f"Failed to retrieve messages: {e}")
        # 可替换为 logging.error 等方式
        log.exception(f"获取消息失败{sender_id},{receiver_id}: {e}")
        raise

async def get_history_chat_by_time_range(sender_id: str,receiver_id: str,start_time: datetime, end_time: datetime):
    try:
        start_time = start_time.date()
        end_time = end_time.date()
        messages = await get_wx_messages_by_session_id(sender_id,receiver_id)

        msgs = [msg for msg in messages if start_time <= msg["created_at"].date() <= end_time]
        data = [{"wx_id":msg["sender_id"],"device_id":msg["receiver_id"],"content": msg["content"], "timestamp": msg["created_at"],"type": msg["content_type"],"is_sent":True if msg["type"]=="回复" else False} for msg in msgs]
        return Result.success(data=data)
    except Exception as e:
        log.exception(f"获取历史聊天记录失败: {e}")
        return Result.fail(msg="获取历史聊天记录失败")

async def get_chat_counts():
    # 计算今天的时间范围
    today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    tomorrow = today + timedelta(days=1)
    today_count = await get_chat_counts_by_dt(today,tomorrow)
    # 计算昨天的时间范围
    today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    yesterday_start = today - timedelta(days=1)
    yesterday_end = today
    yesterday_count = await get_chat_counts_by_dt(yesterday_start,yesterday_end)

    return Result.success(data={
        "today": today_count,
        "yesterday": yesterday_count
    })

async def get_chat_counts_by_dt(d_start,d_end):
    try:
        pipeline = [
            {
                "$match": {
                    "created_at": {
                        "$gte": d_start,
                        "$lt": d_end
                    }
                }
            },
            {
                "$group": {
                    "_id": "$session_id"
                }
            },
            {
                "$count": "total_sessions"
            }
        ]
        # pipeline = [{"$match": {}}]
        # # 执行聚合查询
        result = await ChatMessageModel.aggregate(pipeline).to_list()
        # cursor = ChatMessageModel.aggregate(pipeline)
        # print(type(cursor))
        # result = await cursor.to_list()
        # 返回统计结果
        return result[0]["total_sessions"] if result else 0
    except Exception as e:
        # log.exception(f"获取昨日对话数失败: {e}")
        log.error(f"获取昨日对话数失败: {e}")
        return 0

async def chat_set_lock(sender: str, receiver: str):
    try:
        r = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0, decode_responses=True)
        session_id = ChatMessageModel.generate_session_id(send_id=sender, receiver_id=receiver)
        key = f"lock:{session_id}"
        await r.set(key,"lock")
        return Result.success("ok")
    except Exception as e:
        log.info(f"设置失败: {e}")
        return Result.fail(msg="设置失败")

async def chat_unlock(sender: str, receiver: str):
    try:
        r = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0, decode_responses=True)
        session_id = ChatMessageModel.generate_session_id(send_id=sender, receiver_id=receiver)
        key = f"lock:{session_id}"
        await r.delete(key)
        return Result.success("ok")
    except Exception as e:
        log.info(f"设置失败: {e}")
        return Result.fail(msg="设置失败")

async def send_message(req: MessageParams,sender:SenderTools):
    try:
        from_user_id = await get_wx_id_by_token_key(req.auth_key)
        if not from_user_id:
            raise HTTPException(status_code=400, detail="无效的授权密钥")
        for to_user in req.to_users:
            await create_wx_messages(from_user_id, to_user, "回复", req.msg,content_type=req.type)
            if req.type == 3:
                base64_str = await url_to_base64_async(req.msg)
                sender.send_wx_image(base64_str=base64_str, receiver_id=to_user, key=req.auth_key)
            else:
                sender.send_wx_message(req.msg, to_user, req.auth_key)
        return Result.success()
    except Exception as e:
        log.info(f"Failed to delete message: {e}")
        raise HTTPException(status_code=400, detail="发送消息出现错误")

async def create_chat_mode(mode_name:str,redis_service:AsyncRedisService):
    try:
        await redis_service.set_chat_mode(mode_name)
        return Result.success()
    except Exception as e:
        raise HTTPException(status_code=500, detail="创建聊天模式失败")

async def get_chat_mode(redis_service:AsyncRedisService):
    try:
        mode = await redis_service.get_chat_mode()
        return Result.success(data=mode)
    except Exception as e:
        log.exception(f"获取聊天模式失败: {e}")
        raise HTTPException(status_code=500, detail="获取聊天模式失败")

async def delete_chat_mode(template_name:str,redis_service:AsyncRedisService):
    try:
        await redis_service.delete_chat_mode(template_name)
        return Result.success()
    except Exception as e:
        raise HTTPException(status_code=500, detail="删除聊天模式失败")

async def generate_des_and_set_remark(wx_id:str,device_id:str):
    try:
        msgs = await get_wx_messages_by_session_id(sender_id=wx_id,receiver_id=device_id)
        result = await generate_description(msgs)
        log.info(result)
        await set_friends_remark(device_id=device_id, wx_id = wx_id, remark = result)
        return Result.success(data=result)
    except Exception as e:
        log.exception(f"生成描述失败: {e}")
        raise HTTPException(status_code=500, detail="生成描述失败")